package com.jmxcfc.blfsc.ssq.service.reguser.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jmxcfc.blfsc.common.common.enums.ProcessStateEnum;
import com.jmxcfc.blfsc.common.common.request.BaseRequest;
import com.jmxcfc.blfsc.common.common.response.BaseResponse;
import com.jmxcfc.blfsc.common.exception.AfterOutboundException;
import com.jmxcfc.blfsc.common.exception.BeforeOutboundException;
import com.jmxcfc.blfsc.common.exception.OutboundException;
import com.jmxcfc.blfsc.common.sign.SignRequest;
import com.jmxcfc.blfsc.common.sms.BaseContext;
import com.jmxcfc.blfsc.common.validation.rule.RequestFieldRule;
import com.jmxcfc.blfsc.common.validation.rule.SignRulesUtil;
import com.jmxcfc.blfsc.ssq.common.Constants;
import com.jmxcfc.blfsc.ssq.entity.RegUserPersonalSub;
import com.jmxcfc.blfsc.ssq.modle.response.SsqResponse;
import com.jmxcfc.blfsc.ssq.service.reguser.IRegUserPersonalSubService;
import com.jmxcfc.blfsc.ssq.service.reguser.IRegUserRequestService;
import com.jmxcfc.blfsc.ssq.service.SignatureService;
import com.jmxcfc.blfsc.ssq.util.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.List;
import java.util.Optional;

/**
 * 功能描述
 * 注册个人用户并申请证书实现类
 * 必传参数:account(取身份证号)、name、userType(固定取值1)、applycert(固定取值1)、identity
 * 非必传:mobile

 * @author: pbs
 * @date: 2024年09月02日 22:38
 */
@Service
@Slf4j
public class RegUserRequestServiceImpl implements IRegUserRequestService {

    //注册个人用户并申请证书的请求地址
    @Value("${com.ssq.regUserUrl}")
    private String regUserUrl;


    private SignatureService signatureService;

    private IRegUserPersonalSubService regUserPersonalSubService;

    private RestTemplate restTemplate;



    @Autowired
    public void setSignatureService(SignatureService signatureService) {
        this.signatureService = signatureService;
    }
    @Autowired
    public void setRegUserPersonalSubService(IRegUserPersonalSubService regUserPersonalSubService) {
        this.regUserPersonalSubService = regUserPersonalSubService;
    }

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    /**
     * 请求入口
     * 1、校验必传参数:
     idCode(身份证号对应ssq接口 account用户账户、identity用户证件号)、name(姓名)
     非必传:mobile(电话号)
     * @param requestMessage
     * @return
     */
    @Override
    public BaseResponse<RegUserPersonalSub> sendRequest(BaseRequest<SignRequest<JSONObject>> requestMessage) {
        BaseContext<String> baseContext = new BaseContext<>();
        //头部参数校验规则:业务号
        List<RequestFieldRule<?>> headerElementRules = baseContext.getHeaderElementRules();
        headerElementRules.add(SignRulesUtil.getRequestNoRule());
        //请求体参数校验:
        List<RequestFieldRule<?>> bodyElementRules = baseContext.getBodyElementRules();
        bodyElementRules.add(SignRulesUtil.getAcctNameRule());
        bodyElementRules.add(SignRulesUtil.getIdCodeRule());
        return execute(requestMessage, baseContext);
    }


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void beforeOutbound(BaseRequest<SignRequest<JSONObject>> request, BaseResponse<RegUserPersonalSub> response, BaseContext<String> baseContext) throws BeforeOutboundException {
        String requestNo = request.getHeader().getRequestNo();
        try {
            log.info("请求业务号requestNo:{},注册个人用户并申请证书接口,前置处理:数据落库和参数组装", requestNo);
            RegUserPersonalSub regUserPersonalSub = new RegUserPersonalSub();
            regUserPersonalSub.setRequestNo(requestNo);
            //参数组织、regUserPersonalSub设置值
            String requestParamStr = buildParam(request, regUserPersonalSub);
            //由于是签名参数追加为url参数:/openapi/v2/user/reg/?developerId=aaaaaa&rtick=14840209310001&signType=rsa
            String urlPathParams = signatureService.buildUrlPathParams(regUserUrl, "", requestParamStr);
            //请求路径的url的参数
            baseContext.setExtendStr(urlPathParams);
            //设置请求
            baseContext.setRestHttpEntity(HttpUtils.creatRequestEntity(requestParamStr));
            //保存数据
            regUserPersonalSubService.save(regUserPersonalSub);
            //主键
            baseContext.setRecordId(regUserPersonalSub.getId());
            log.info("请求业务号requestNo:{},注册个人用户并申请证书接口,前置处理结束", requestNo);
        } catch (Exception e) {
            log.error("请求业务号requestNo:{},前置处理异常:{}", requestNo, e.getMessage(), e);
            throw new BeforeOutboundException(e.getMessage(), e);
        }
    }

    /**
     * 外呼请求
     * 请求的url的格式:regUserUrl + urlParams
     * regUserUrl = host + method
     * @param request
     * @param response
     * @param baseContext
     * @throws OutboundException
     */
    @Override
    public void outbound(BaseRequest<SignRequest<JSONObject>> request, BaseResponse<RegUserPersonalSub> response, BaseContext<String> baseContext) throws OutboundException {
        try{
            //请求url的,必须要用URL,否则restTemplate会对url进行
            URI requestUrl = new URI( StringUtils.join(regUserUrl, baseContext.getExtendStr()));
            log.info("请求业务号requestNo:{},注册个人用户并申请证书,发送请求外呼,请求地址:{},请参数:{}",request.getHeader().getRequestNo(),requestUrl,baseContext.getRestHttpEntity().getBody());
            String resp = restTemplate.postForObject(requestUrl, baseContext.getRestHttpEntity(), String.class);
            log.info("请求业务号requestNo:{},注册个人用户并申请证书,发送请求外呼,响应内容:{}", request.getHeader().getRequestNo(), resp);
            baseContext.setRestResponse(resp);
        } catch (Exception e) {
            log.error("请求业务号requestNo:{},注册个人用户并申请证书,发送请求外呼异常:{}", request.getHeader().getRequestNo(), e.getMessage());
            throw new OutboundException(e.getMessage(), e);
        }
    }

    /**
     * {
     *   "errno": 0,
     *   "cost": 533,
     *   "data": {
     *     "taskId": "170217170217942"
     *   },
     *   "errmsg": ""
     * }
     * 状态判断:
     errno=0 且 taskId不为空,则成功=》ProcessState=SUCCESS
     否则失败=》ProcessState=FAILURE
     * @param request
     * @param response
     * @param baseContext
     * @throws AfterOutboundException
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void afterOutbound(BaseRequest<SignRequest<JSONObject>> request, BaseResponse<RegUserPersonalSub> response, BaseContext<String> baseContext) throws AfterOutboundException {
        String requestNo = request.getHeader().getRequestNo();
        try{
            log.info("请求业务号requestNo:{},注册个人用户并申请证书接口,后置处理:解析响应结果", requestNo);
            RegUserPersonalSub regUserPersonalSub = new RegUserPersonalSub();
            regUserPersonalSub.setRequestNo(requestNo);
            //注意这边是根据主键更新
            regUserPersonalSub.setId(baseContext.getRecordId());
            SsqResponse ssqResponse = JSON.parseObject(baseContext.getRestResponse(),SsqResponse.class);
            //错误码值,0:成功
            String errno = ssqResponse.getErrno();
            //错误信息描述
            String errmsg = ssqResponse.getErrmsg();
            log.info("请求业务号requestNo:{},注册个人用户并申请证书接口,响应的结果 errno:{},errmsg:{}", requestNo, errno, errmsg);
            if (StringUtils.equals(errno, Constants.ERRNO_0)) {
                JSONObject data = Optional.ofNullable(ssqResponse.getData()).orElseGet(JSONObject::new);
                String taskId = data.getString(Constants.TASK_ID);
                if (StringUtils.isNotBlank(taskId)) {
                    response.getHeader().setProcessState(ProcessStateEnum.SUCCESS);
                    regUserPersonalSub.setTaskId(taskId);
                }else {
                    log.error("请求业务号requestNo:{},注册个人用户并申请证书接口响应的taskId字段为空:{}",requestNo,taskId);
                    response.getHeader().setProcessState(ProcessStateEnum.FAILURE);
                }
            }else {
                response.getHeader().setProcessState(ProcessStateEnum.FAILURE);
            }
            regUserPersonalSub.setErrno(errno);
            regUserPersonalSub.setErrmsg(errmsg);
            regUserPersonalSubService.updateById(regUserPersonalSub);
            response.getHeader().setResCode(errno);
            response.getHeader().setResMessage(errmsg);
            response.setBody(regUserPersonalSub);
            log.info("请求业务号requestNo:{},注册个人用户并申请证书接口,后置处理结束", requestNo);
        } catch (Exception e) {
            log.error("请求业务号requestNo:{},注册个人用户并申请证书接口,后置处理异常:{}", requestNo, e.getMessage(), e);
            throw new AfterOutboundException(e.getMessage(), e);
        }
    }

    /**
     *
     * {
     *   "account": "test@bestsign.cn",
     *   "name": "张三",
     *   "userType": "1",
     *   "mail": "test@bestsign.cn",
     *   "mobile": "13800001234",
     *   "credential": {
     *     "identity": "100123199001010011",
     *     "identityType": "0",
     *     "contactMail": "test@bestsign.cn",
     *     "contactMobile": "13800001234",
     *     "province": "浙江省",
     *     "city": "杭州市",
     *     "address": "xx路xx号"
     *   },
     *   "applyCert": "1"
     * }
     * 参数组装
     * @param request
     * @param regUserPersonalSub
     */
    private String buildParam(BaseRequest<SignRequest<JSONObject>> request, RegUserPersonalSub regUserPersonalSub) {
        JSONObject requestParam = new JSONObject();
        SignRequest<JSONObject> signRequestBody = request.getBody();
        //账户(取证件号码)
        requestParam.put(Constants.ACCOUNT, signRequestBody.getIdCode());
        //姓名
        requestParam.put(Constants.NAME, signRequestBody.getAcctName());
        //用户类型:1表示个人
        requestParam.put(Constants.USER_TYPE, "1");
        //手机号
        requestParam.put(Constants.MOBILE, signRequestBody.getPhoneNo());
        //是否需要申请证书:1(需要)、0(无需)
        requestParam.put(Constants.APPLY_CERT,"1");


        JSONObject credential = new JSONObject();
        credential.put(Constants.IDENTITY, signRequestBody.getIdCode());
        //证件类型:默认0 ("0"表示身份证)
        credential.put(Constants.IDENTITY_TYPE,Constants.IDENTITY_TYPE_0);
        requestParam.put("credential", credential);


        regUserPersonalSub.setAccount(signRequestBody.getIdCode());
        regUserPersonalSub.setName(signRequestBody.getAcctName());
        regUserPersonalSub.setUserType(requestParam.getString(Constants.USER_TYPE));
        regUserPersonalSub.setMobile(signRequestBody.getPhoneNo());
        regUserPersonalSub.setIdentity(signRequestBody.getIdCode());
        regUserPersonalSub.setIdentityType(credential.getString(Constants.IDENTITY_TYPE));
        regUserPersonalSub.setApplyCert(requestParam.getString(Constants.APPLY_CERT));
        log.info("请求业务号requestNo:{},参数组织完成,参数:{}", request.getHeader().getRequestNo(), JSON.toJSONString(requestParam));
        return JSON.toJSONString(requestParam);
    }


}